import os
import re
import xmindparser
import pandas as pd
from datetime import datetime
import argparse


def parse_xmind_to_excel(xmind_file, excel_file=None):
    try:
        # 解析 XMind 文件
        xmind_content = xmindparser.xmind_to_dict(xmind_file)
        testcase = []

        # 获取中心主题（项目版本）
        root_topic = xmind_content[0]['topic']
        root_title = root_topic.get('title')
        # 分离项目名称和版本信息
        pattern = r'^(.*?)([vV]\d+\.\d+)$'
        match = re.match(pattern, root_title)
        if match:
            project_name = match.group(1).strip()
            version_name = match.group(2)
        else:
            project_name = root_title
            version_name = None

        # 检查根节点的下一级是否为版本节点
        first_level_topics = root_topic.get('topics', [])
        if not version_name:
            for version_topic in first_level_topics:
                version_name = version_topic['title'].replace('[version]', '').strip()
                # 从版本节点开始递归
                find_all_case_node(testcase, version_name, '', [], '', version_topic)
        else:
            # 从根节点开始递归
            find_all_case_node(testcase, version_name, '', [], '', root_topic)

        # 将用例数据列表转换为 DataFrame
        df = pd.DataFrame(testcase)
        df['项目名称'] = project_name
        columns = ['项目名称'] + [col for col in df.columns if col != '项目名称']
        df = df[columns]

        # 写入 Excel 文件
        # 获取当前脚本文件的绝对路径
        current_file_path = os.path.abspath(__file__)
        # 获取当前脚本文件所在的目录路径
        current_dir = os.path.join(os.path.dirname(current_file_path), 'excel_file')
        current_time = datetime.now().strftime("%Y%m%d")
        xmind_name = os.path.basename(xmind_file).split('.')[0]
        excel_path = os.path.join(current_dir, f'excel_{xmind_name}_{current_time}.xlsx')
        if excel_file:
            excel_path = excel_file
        else:
            # 获取当前脚本文件的绝对路径
            current_file_path = os.path.abspath(__file__)
            # 获取当前脚本文件所在的目录路径
            current_dir = os.path.join(os.path.dirname(current_file_path), 'excel_file')
            current_time = datetime.now().strftime("%Y%m%d")
            xmind_name = os.path.basename(xmind_file).split('.')[0]
            excel_path = os.path.join(current_dir, f'excel_{xmind_name}_{current_time}.xlsx')
        df.to_excel(excel_path, index=False)
        return f"【XMIND转EXCEL】成功将 {xmind_file} 转换为 {excel_path}, 共 {len(testcase)} 条用例"
    except:
        return f"【XMIND转EXCEL】转换{xmind_file}失败"


def find_all_case_node(testcase, version_name, requirement_name, module_stack, case_type, parent_topic):
    for sub_topic in parent_topic.get('topics', []):
        if  sub_topic['title'].startswith('[reg.]'):
            continue
        if '[case]' in sub_topic['title'] and '[reg.]' not in sub_topic['title']:
            # 直接是用例节点
            module_name = '-'.join(module_stack) if module_stack else ''
            if '[step]' in sub_topic.get('note', ''):
                case_struc='mark'
                case = process_case_topic(version_name, requirement_name, module_name, case_type, sub_topic, case_struc)
                testcase.append(case)
                find_all_case_node(testcase, version_name, requirement_name, module_stack, case_type, sub_topic)
            elif '[step]' in str(sub_topic.get('topics', [])):
                case_struc='node'
                case = process_case_topic(version_name, requirement_name, module_name, case_type, sub_topic, case_struc)
                testcase.append(case)
            else:
                raise Exception('暂不支持当前用例结构')    
        elif '[req.]' in sub_topic['title']:
            new_requirement_name = sub_topic['title'].replace('[req.]', '').strip()
            # 递归处理需求节点及其子节点
            find_all_case_node(testcase, version_name, new_requirement_name, module_stack, case_type, sub_topic)         
        elif '[module]' in sub_topic['title']:
            module_name = sub_topic['title'].replace('[module]', '').strip()
            # 将模块名压入栈中
            module_stack.append(module_name)
            # 处理模块及子模块下的用例
            find_all_case_node(testcase, version_name, requirement_name, module_stack, '', sub_topic)
            module_stack.pop()
        elif '[s-module]' in sub_topic['title']:
            sub_module_name = sub_topic['title'].replace('[s-module]', '').strip()
            module_stack.append(sub_module_name)
            # 递归处理子模块下的内容
            find_all_case_node(testcase, version_name, requirement_name, module_stack, case_type, sub_topic)
            module_stack.pop()
        elif '[type]' in sub_topic['title']:
            # 是用例类型节点
            new_case_type = sub_topic['title'].replace('[type]', '').strip()
            # 递归查找该类型下的用例节点
            find_all_case_node(testcase, version_name, requirement_name, module_stack, new_case_type, sub_topic)
        else:
            # 继续递归查找用例节点
            find_all_case_node(testcase, version_name, requirement_name, module_stack, case_type, sub_topic)


def process_case_topic(version_name, requirement_name, module_name, case_type, case_topic, case_struc='marke'):
    case_title = case_topic['title'].replace('[case]', '').strip()
    # 获取备注中的步骤和预期结果
    precondition = ''
    steps = ''
    expected_result = ''
    # 当前兼容两种结构的xmind，1、case信息在备注里 2、case-步骤-预期结果
    if 'mark' in case_struc:
        note = case_topic.get('note', '')
        if '[pre]' in note:
            precondition = note.split('[pre]')[1].split('[step]')[0].strip()
        if '[step]' in note:
            steps = note.split('[step]')[1].split('[result]')[0].strip()
        if '[result]' in note:
            expected_result = note.split('[result]')[1].strip()
    elif 'node' in case_struc:
        step_topics = case_topic.get('topics', [])
        if step_topics:
            step_topic = step_topics[0]
            note = step_topic.get('title', '')
            if '[pre]' in note:
                precondition = note.split('[pre]')[1].split('[step]')[0].strip()
            if '[step]' in note:
                steps = note.split('[step]')[1].strip()

            result_topics = step_topic.get('topics', [])
            if result_topics:
                expected_result = result_topics[0].get('title', '').replace('[result]', '').strip()
    else:
        raise Exception('暂不支持当前用例结构')

    # 判断是否为冒烟用例
    is_smoke_case = '是' if 'flag-red' in case_topic.get('makers', []) else '否'
    # 获取用例优先级
    priority = ''
    for marker in case_topic.get('makers', []):
        if marker.startswith('priority-'):
            if marker=="priority-1":
                priority = "高"
            elif marker=="priority-2":
                priority = "中"
            else:
                priority = "低"
    # 以字典形式存储用例数据
    case_data = {
        '版本名称':version_name,
        '需求名称': requirement_name,
        '功能模块': module_name,
        '用例类型': case_type,
        '是否冒烟用例': is_smoke_case,
        '优先级': priority,
        '用例标题': case_title,
        '前置条件': precondition,
        '测试步骤': steps,
        '预期结果': expected_result,
    }
    return case_data

if __name__ == "__main__":
    # 创建 ArgumentParser 对象
    parser = argparse.ArgumentParser(description='将 Excel 文件转换为 XMind 文件')

    # 添加命令行参数
    parser.add_argument('xmind_file', type=str, help='输入的 XMind 文件路径')
    parser.add_argument('-o', '--output', type=str, 
                        help='输出的 excel 文件路径，非必填，默认为 excel_{xmind_file}_{%Y%m%d}.xlsx')


    # 解析命令行参数
    args = parser.parse_args()

    # 获取传入的参数值
    xmind_file = args.xmind_file
    excel_file = args.output

    # 调用转换函数
    parse_xmind_to_excel(xmind_file, excel_file)

